module sw.siteconfig;
import std.stdio, std.string, nazo.file, nazo.savedata, std.conv, std.c.process, nazo.http, nazo.serialize, std.typetuple;

/**
 * サイトの設定。
 * ファイルに保存するならflashを呼ぶこと。
 */
struct SiteConfig{
  struct SizeConfigData_v2{
    struct SizeConfigData_v1{
      ///サイト名
      string siteName="サイト名";
      ///サイトの概要
      string siteDescription="サイトの説明";
      ///管理者のメールアドレス
      string mailAddr="nobody@example.com";
      ///トップページの名前
      string topPageName="Front Page";
      ///管理者の名前
      string manager="管理人の名前";
      ///CSS
      string cascadingStyleSheet="style.css";
      ///favIcon
      string favIcon="icon.png";
      ///標準の言語
      string defaultLanguage="ja";
      ///環境変数PATH_INFOを使うか否か
      bool usePathInfo=true;
      ///Last-Modifiedを使うか否か
      bool useLastModified=false;
      ///個人的Wikiモードにするか否か
      bool personalMode=false;
      ///一般ユーザーが新しいページの作成をするのを許可するか
      bool canNewPage=true;
      ///シンクロ元URI
      string synchronizeURI="";
      ///アップロードの標準での一ページ中の表示アイテムの個数
      ///Bugs: should rename to showItemPerPage
      uint defaultItemPerPage=10;
      ///アップロードできるファイルの最大サイズ(単位はKiB)
      uint uploadMaxSize=1024;
      ///保存しておくファイルの最大個数(0なら制限無し)
      uint uploadMaxItem=0;
      ///文章のライセンス
      uint wikiDocumentLicense=0;
    }
    SizeConfigData_v1 data_v1;
    alias data_v1 this;
    ///最大サイズ
    ulong maxSize=10*1024*1024;
    ///ヘッダ
    string header="";
    ///フッタ
    string footer="";
  }
  static SizeConfigData_v2 data_v2;
  alias data_v2 this;

  ///管理者のパスワードのハッシュ
  string passhash;
  ///現在使用しているサイズ
  ulong usingSize;
  void flash(){
    nazo.file.write(fileName, serialize!(uint)(2)~serialize(data_v2));
  }
  string fileName;
  void reload(){
    if(!exists(fileName)){
      this = this.init;
      return;
    }
    auto f = cast(ubyte[])read(fileName);
    auto var = *cast(uint*)f.ptr;
    auto val = f[4..$];
    if(var < 0x10){
      if(var == 1)
        deserialize(val, this.data_v1);
      else if(var == 2)
        deserialize(val, this.data_v2);
      else
        throw new Exception("unsupported version");
      return;
    }
    // load setting file version 0
    scope sd=new SaveData(fileName);
    string tmp;
    tmp=sd.getValue("name");
    if(tmp.length)this.siteName=tmp;
    tmp=sd.getValue("description");
    if(tmp.length)this.siteDescription=tmp;
    tmp=sd.getValue("mailAddr");
    if(tmp.length)this.mailAddr=tmp;
    tmp=sd.getValue("topPageName");
    if(tmp.length)this.topPageName=tmp;
    tmp=sd.getValue("manager");
    if(tmp.length)this.manager=tmp;
    tmp=sd.getValue("cascadingStyleSheet");
    if(tmp.length)this.cascadingStyleSheet=tmp;
    tmp=sd.getValue("favIcon");
    if(tmp.length)this.favIcon=tmp;
    tmp=sd.getValue("defaultLanguage");
    if(tmp.length)this.defaultLanguage=tmp;
    tmp=sd.getValue("usePathInfo");
    if(tmp.length)this.usePathInfo=(tmp=="true")?true:false;
    tmp=sd.getValue("useLastModified");
    if(tmp.length)this.useLastModified=(tmp=="true")?true:false;
    tmp=sd.getValue("personalMode");
    if(tmp.length)this.personalMode=(tmp=="true")?true:false;
    tmp=sd.getValue("canNewPage");
    if(tmp.length)this.canNewPage=(tmp=="true")?true:false;
    tmp=sd.getValue("synchronizeURI");
    if(tmp.length)this.synchronizeURI=tmp;
    tmp=sd.getValue("defaultItemPerPage");
    if(tmp.length)this.defaultItemPerPage=.toUint(tmp);
    tmp=sd.getValue("uploadMaxSize");
    if(tmp.length)this.uploadMaxSize=.toUint(tmp);
    tmp=sd.getValue("uploadMaxItem");
    if(tmp.length)this.uploadMaxItem=.toUint(tmp);
    tmp=sd.getValue("wikiDocumentLicense");
    if(tmp.length)this.wikiDocumentLicense=.toUint(tmp);
    tmp=sd.getValue("maxSize");
    if(tmp.length)this.maxSize=.toUlong(tmp);
  }
  static SiteConfig opCall(string fileName){
/*//文字列の退避が出来ない
    if(exists("/dev/shm/siteconfig")){
      m = cast(SiteConfig*)std.file.read("/dev/shm/siteconfig");
      return;
    }*/
    SiteConfig cfg;
    cfg.fileName=fileName;
    cfg.reload();

    if(!exists("admin.pwd"))
      goto pwderror;
    cfg.passhash = cast(string)read("admin.pwd");
    if(!cfg.passhash)
      goto pwderror;
    if(cfg.passhash[$-1]=='\n')cfg.passhash=cfg.passhash[0..$-1];
    cfg.usingSize = getSize("./");
//    write("/dev/shm/siteconfig", (cast(ubyte*)m)[0..SiteConfig.sizeof]);
    return cfg;
    pwderror:{
      HttpResponse.write("admin.pwd doesn't exist!\n\nadmin.pwdの作り方: zenity --entry --hide-text --title=\"admin.pwdの生成\" --text=\"パスワードを入力してください。\" | tr -d '\n' | md5sum | sed  's/[- ]//g' > admin.pwd\n\nFIXME: gnomeのzenityとtextutilsに依存してるのでもっと簡単な方法を考える必要あり?\nただし、web経由だとインストール時に乗っ取られる可能性がある。");
      exit(0);
      assert(0);
    }
  }
}
